home *** CD-ROM | disk | FTP | other *** search
/ MacTech 1 to 12 / MacTech-vol-1-12.toast / Source / MacTech® Magazine / Volume 04 - 1988 / 04.02 Feb 88 / Rotate Source Code / rotString ƒ / rotate.a next >
Encoding:
Text File  |  1987-12-30  |  11.9 KB  |  329 lines  |  [TEXT/MPS ]

  1.     INCLUDE    'SysEqu.a'    ;the usual system equates & macros    
  2.     INCLUDE    'Traps.a'
  3.     INCLUDE    'QuickEqu.a'
  4.     
  5. newPtrClear FUNC EXPORT
  6.     
  7.     IMPORT    SAVERETA1
  8.     
  9.     MOVE.L    (SP)+,A1
  10.     MOVE.L    (SP)+,D0
  11.     _NewPtr    clear
  12.     MOVE.L    A0,(SP)
  13.     JMP    SAVERETA1
  14.     
  15.     ENDF
  16.  
  17.  
  18. Rotate PROC EXPORT
  19. ;------------------------------------------------------------------------
  20. ;    
  21. ; PROCEDURE    Rotate (sourceMap, destMap : bitMap );
  22. ;    
  23. ; given a source and destination bitmap rotate it CCW 90°…
  24. ; bitmap can be of any size, we will align on a word boundaries (v & h)
  25. ;
  26. ;-------------------------------------------------------------------------------
  27. ;    a0 = result of _newPtr call            |    d0 = size of bitMap to allocate
  28. ;    a1 = ptr to src bitMap                |    d1 = width/2  (source)
  29. ;    a2 = ptr to dest bitMap                |    d2 = height/2 (source)
  30. ;    a3 = dest bits                        |    d3 = left | top
  31. ;    a4 = copy of dest bits                |    d4 = ctrPt.h
  32. ;    a5 = not used                        |    d5 = ctrPt.v
  33. ;    a6 = not used                        |    d6 = right | bottom
  34. ;    a7 = not used                        |    d7 = rowBytes of dest bitMap
  35. ;-------------------------------------------------------------------------------
  36. ; ***********************************************************************
  37. ; *                                                                        *
  38. ; *        Initialize destination bitMap (destMap), etc…                    *
  39. ; *                                                                        *
  40. ; ***********************************************************************
  41. ; parameter offsets
  42. ;
  43. DestMap        EQU    4+4                ; offset to dest bitmap ^
  44. SourceMap    EQU DestMap + 4        ; offset to source bitmap ^
  45. ;
  46. ; create local stack frame, and save some registers
  47. ; make room for dest rect to be passed back
  48. ;
  49.     link    a6,#0                ; set up a stack frame (no bytes)
  50.     movem.l    d3-d7/a2-a5,-(sp)    ; save registers pascal may need
  51.  
  52.     move.l    SourceMap(a6),a1    ; point to the source BitMap
  53.     move.l    DestMap(a6),a2        ; point to the dest BitMap
  54. ;
  55. ; compute height of source BitMap rounded up to nearest word
  56. ;                                
  57.     move.w    bounds+bottom(a1),d7; get bottom and put in d7
  58.     sub.w    bounds+top(a1),d7    ; bottom - top = height, put in d7
  59.     move.w    d7,d0                ; save a copy of height for later
  60.                                 ; rnd = (height+15)/16, follows:
  61.     addi.w    #15,d7                ; add 15 to the height, put in d7
  62.     lsr        #4,d7                ; divide by 16
  63.     lsl        #1,d7                ; multiply by 2 = rowBytes of dest bitMap
  64. ;
  65. ; d7 now contains rowBytes of dest bitMap
  66. ;
  67. ; now compute the destRect for dest bitMap
  68. ;
  69.                                 ; compute center point of Source rect
  70.                                 ; note the center points are not necess. the
  71.                                 ; same in the vert dir. relative to srcMap
  72.                                 ; because of rounding that follows (i.e. height
  73.                                 ; of srcMap is dir. prop. to RowBytes of destMap)
  74.     lsr        #1,d0                ; divide height by 2
  75.     move.w    d0,d2                ; make a copy of height/2 for later
  76.     move.w    bounds+top(a1),d5    ; get 'top' of source rect
  77.     add.w    d0,d5                ; d5 now contains vert component of ctr pt
  78.                                 ; compute the width of src rect & put in d4
  79.     move.w    bounds+right(a1),d3    ; get right and put in d3
  80.     sub.w    bounds+left(a1),d3    ; right - left = width, put in d3
  81.     lsr        #1,d3                ; divide width by 2
  82.     move.w    d3,d1                ; make a copy of width/2 for later
  83.     move.w    bounds+right(a1),d4    ; get right of source rect
  84.     sub.w    d3,d4                ; d4 now contains horiz component of ctr pt
  85. ;
  86. ; now get center point and compute bounds for dest bitMap
  87. ; height and width are reversed now for the 2 bitMaps
  88. ;
  89. ; left    :=ctrPt.h - height/2
  90. ; top    :=ctrPt.v - width/2
  91. ; right    :=ctrPt.h + height/2
  92. ; bottom:=ctrPt.v + width/2
  93. ; SetRect(rect, left, top, right, bottom) put data in direct to
  94. ; avoid the overhead of a trap call
  95. ;
  96.                                 ; compute 'top'
  97.     move.w    d5,d3                ; get a copy of ctrPt.v and put in d3
  98.     sub.w    d1,d3                ; ctrPt.v - width/2 = 'top' in d3
  99.     swap    d3                    ; move 'top' to hiword
  100.                                 ; compute 'left'
  101.     move.w    d4,d3                ; get a copy of ctrPt.h and put in loword d3
  102.     sub.w    d2,d3                ; ctrPt.h - height/2 = 'left' in loword d3
  103. ;
  104. ; we now have 'top' in hiword & 'left' in loword d3
  105. ;
  106.                                 ; compute 'bottom'
  107.     move.w    d5,d6                ; get a copy of ctrPt.v in of d3
  108.     add.w    d1,d6                ; ctrPt.v + width/2 = 'bottom' in d3
  109.     swap    d6                    ; move 'bottom' to hiword    
  110.                                 ; compute 'right'
  111.     move.w    d4,d6                ; get a copy of ctrPt.h and put in loword d6
  112.     add.w    d2,d6                ; ctrPt.h + height/2 = 'right' in loword d6
  113. ;
  114. ; we now have 'bottom' in hiword & 'right' in loword d6
  115. ;
  116. ; assign data to dest bitMap structure directly
  117. ;
  118.     move.w    d7,rowBytes(a2)        ; put in rowBytes direct for dest bitMap
  119.     move.l    d3,bounds+topLeft(a2)    ; put the coord pair in direct
  120.     move.l    d6,bounds+botRight(a2)    ; put the coord pair in direct
  121.     move.w    d7,d0                ; put rowbytes in d0
  122.     mulu    rowBytes(a1),d0        ; multiply rowBytes src*dest = d0
  123.     lsl        #3,d0                ; multiply d0 by 8 for size of dest bitMap
  124.     _NewPtr    clear                ; allocate size of dest bitMap (a2 pts to it) 
  125.     move.l    a0,baseaddr(a2)        ; move contents of a0 to baseAddr field
  126.                                 ; of dest bitMap structure
  127.                                 
  128. ;-------------------------------------------------------------------------------
  129. ;    a0 = baseAddr for our locals        |    d0 = rowbytes of srcMap
  130. ;    a1 = points to bits of src bitMap    |    d1 = width/2     (source)
  131. ;    a2 = ptr to dest bitMap                |    d2 = height/2      (source)
  132. ;    a3 = dest bits                        |    d3 = current word srcMap
  133. ;    a4 =                                 |    d4 = copy of width of srcMap
  134. ;    a5 = not used                        |    d5 = current destMap word
  135. ;    a6 = not used                        |    d6 = insideLoop count (current bit)
  136. ;    a7 = not used                        |    d7 = rowBytes of dest bitMap
  137. ;-------------------------------------------------------------------------------
  138. ; ***********************************************************************
  139. ; *                                                                        *
  140. ; *        Start actual rotation of bitMaps                                *
  141. ; *                                                                        *
  142. ; ***********************************************************************
  143. ; Assumptions:
  144. ; height of destination bitMap = rowBytes of srcMap
  145. ;
  146. ; Get the baseAddr for our locals into a0 - this will make our program much
  147. ; more readable as we will let the assembler do all the addr location calcs
  148. ; for us. The addresses will be a fixed number while the programs is
  149. ; (locked down) and running, therefore, there is no runtime penalty for
  150. ; doing this addr calculation
  151. ;
  152.  
  153.     lea    localVars,a0
  154. ;
  155. ; initialize d0 to contain the pointer to the srcMap
  156. ;
  157.     move.w    rowbytes(a1),d0        ; get rowbytes of srcMap
  158.     
  159. ;
  160. ; get regs pointing to bits
  161. ;
  162.     move.l    (a1),a1                ; a1 pts to BITS of src bitMap    
  163.     move.l    (a2),a3                ; a3 pts to BITS of dest bitMap
  164.  
  165. computeInitLowerLeft
  166. ; compute the lower left corner of the destMap - this maps to the upper left
  167. ; corner of the srcMap and will be used as base from which to offset into
  168. ; the dest map when we need to set a bit
  169. ;
  170.     clr.l    d1                    ; clear d1 
  171.     move.w    d0,d1                ; load rowBytes of srcMap
  172.                                 ; (rowBytes of srcMap = ht of destMap)
  173.     lsl.w    #3,d1                ; multiply by 8 to get ht of destMap when rot'd
  174.     mulu.w    d7,d1                ; multiply by rowbytes(destMap) = #words in
  175.     sub.w    d7,d1                ; destMap less one row
  176.     add.l    a3,d1                ; add the computed offset to the baseAddr of destMap
  177.     move.l    d1,lowerLeft-localVars(a0)    ; init lowerLeft
  178. ;
  179. ;-------------------------------------------------------------------------------
  180. ;    a0 = baseAddr for our locals        |    d0 = rowbytes of srcMap
  181. ;    a1 = points to bits of src bitMap    |    d1 = SCRATCH
  182. ;    a2 = SCRATCH                        |    d2 = colmCounter
  183. ;    a3 = dest bits                        |    d3 = current srcMap word 
  184. ;    a4 = SCRATCH                        |    d4 = colmBitLoop counter
  185. ;    a5 = not used                        |    d5 = current word destMap
  186. ;    a6 = not used                        |    d6 = insideLoop count (current bit)
  187. ;    a7 = not used                        |    d7 = rowBytes of dest bitMap
  188. ;-------------------------------------------------------------------------------
  189. ;
  190.  
  191. ;    _Debugger;
  192.     
  193. ; init wordCount to zero 
  194. ;
  195.     move.w    #0,wordCount-localVars(a0)    ; set wordCount to one before we start
  196. ;
  197. ; init colmLoop counter
  198. ;
  199.     move.w    d7,d2                ; get rowBytes(dest)
  200.     lsr        #1,d2                ; divide by 2 - d2 now contains the outer counter
  201.     move.w    d2,colmCount-localVars(a0)    ; put the max value away for reference
  202.     moveq.l    #0,d2                ; set d2 to zero since we use it for the counter
  203.  
  204. colmLoop
  205. ;
  206. ; this is the outside loop
  207. ;
  208.     move.w    #15,d4                ; init colmBitLoop counter to 15
  209.     move.l    lowerLeft-localVars(a0),currentWord-localVars(a0)    ; init currentWord    
  210.  
  211. colmBitLoop
  212. ;
  213. ; this is the loop that does the bit counting in the destMap - it is really a
  214. ; misuse of the 'dbra' instruction since it is not an independent loop but it
  215. ; is a quite cheap method of doing our counting
  216. ;
  217.  
  218. rowLoop
  219. ;
  220. ; loop across each row in the srcMap and keep count each time we do a row
  221. ; this 'rowCount' will used to compute the offset from 'lowerLeft'
  222. ;
  223.     move.w    (a1),d3                        ; get a word to rotate into d3
  224.     addq.w    #2,wordCount-localVars(a0)    ; add 1 for each word •••jdo•••
  225.     moveq.l    #0,d6                        ; clear d6    
  226.     move.w    #15,d6                        ; initialize the inside (bit) loop counter
  227.     
  228. innerLoop
  229. ;
  230. ; we will test each bit (15->0 ie. lt to rt) if it is set then we worry
  231. ; about going out and setting it in destMap otherwise we just increment the
  232. ; counters and test the next bit (cause we cleared them all at init)
  233. ;
  234.     btst    d6,d3                ; test bit pointed to in the current src word
  235.                                 ; by the inner (bit) loop counter
  236.     beq        NoBitToChange        ; if bits not set skip to next cause we cleared
  237.                                 ; them at init of bitMap else set the corresponding
  238.                                 ; bit before we bump the counter to the next bit
  239. ;
  240. ; bit needs to be set - get the word from memory, set bit and put it back
  241. ; this is very time consuming as each word is moved in/out of memory 16 times
  242. ; and a good place to look at for optimization - it probably means a complete
  243. ; rethink of the way we are doing this now
  244. ;
  245.     nop
  246.     movea.l    currentWord-localVars(a0),a2    ; get addr of currentWord
  247.     move.w    (a2),d5                            ; get currentWord
  248.     bset    d4,d5                            ; set proper bit in currentWord
  249.     move.w    d5,(a2)                            ; put the currentWord word back
  250.                                             ; into destMap (memory pt'd to by a3)    
  251.     nop
  252.     
  253. noBitToChange
  254. ;
  255. ; bit was cleared at init of bitMap so we come here to increment the
  256. ; counters - we need to move over 1 bit in the srcWord and up 1 row in
  257. ; our destMap (which is always subtracting rowBytes 
  258. ;
  259.     sub.l    d7,currentWord-localVars(a0)    ; subtract rowBytes(destMap) from current word
  260.     dbra    d6,innerLoop                    ; keep looping (thru bits) till d6 = -1
  261.     addq.l    #2,a1                            ; point to the next word in srcMap - this will take
  262.                                             ; us all the way thru the srcMap as simple as that !
  263.                                             ; Its the destMap that requires all the dang loops
  264.                                             ; to get the addr of the corresponding word in the
  265.                                             ; destMap
  266. doneWithSrcWord
  267. ;
  268. ; at this point we've just completed a word from the srcMap
  269. ;
  270.     cmp        wordCount-localVars(a0),d0        ; cmp wordCount to rowBytes-are we done with a row ?
  271.     bne        rowLoop                            ; no - do another word
  272.     
  273. doneWithRow
  274. ;
  275. ; we just completed a row so add 2 to the count
  276. ;
  277.     move.w    #0,wordCount-localVars(a0)        ; •••jdo••• reset wordCount to zero
  278.  
  279. ;    
  280. ; the following use of dbra keeps track of our destMap bit for us
  281. ;
  282.     move.l    lowerLeft-localVars(a0),currentWord-localVars(a0)    ; re-init currentWord    
  283.                                         ; set the currentWord to the lowerLeft(current)
  284.                                         ; lowerLeft is moved over (right) by a word each
  285.                                         ; time we do a row in the srcMap
  286.     dbra    d4,colmBitLoop                ; go thru the bits (15->0) in the
  287.                                         ; destMap - then exit and do it
  288.                                         ; again for rowBytes/2 times
  289.  
  290. doneWithDestWord
  291. ;
  292. ; were done counting thru the bits of a destMap word - at this point we have
  293. ; actually finished a column in the destMap. The column is a multiple of
  294. ; 16 bits wide (and being at least 1 colm) and as tall as the destMap is
  295. ; (which is also equal to rowBytes of the srcMap)
  296. ;
  297.     addq.l    #2,lowerLeft-localVars(a0)        ; this moves us into the next
  298.                                             ; 'column' of bits in the destMap
  299.     addq.w    #1,d2                            ; add 1 to the colmLoop counter
  300.     cmp        colmCount-localVars(a0),d2        ; are we done yet ?
  301.     bne        colmLoop                        ; no - do it again
  302.                                             ; else we're done
  303. ;
  304. ; were done so lets do our clean-up/restore and go away gracefully
  305. ;
  306. cleanUpTime                        ; clean-up and get outta dodge
  307.     movem.l    (sp)+,d3-d7/a2-a5    ; restore registers
  308.     unlk    a6                    ; clean up stack frame
  309.     move.l    (sp)+,a0            ; return address
  310.     add.l    #8,sp                ; pop parameters off stack
  311.     jmp        (a0)                 ; bye y'all!
  312.     
  313. ;
  314. ; set up our data storage area
  315. ;
  316. localVars                        ; the beginning of our local var storage area
  317. colmCount        ds.w    1
  318. currentWord        ds.l    1
  319. lowerLeft        ds.l    1
  320. wordCount        ds.w    1
  321.  
  322.     ENDP
  323.     
  324.     END
  325.     
  326.  
  327.